import { h } from 'vue'
import { XIcon } from '@/components/x-icon'
import JSEncrypt from 'jsencrypt'
import router from '@/router'
const { VITE_JSENCRYPT_RSA } = import.meta.env
/**
 * clean Array
 * */
export function cleanArray(actual) {
  const newArray = []
  for (let i = 0; i < actual.length; i++) {
    if (actual[i]) {
      newArray.push(actual[i])
    }
  }
  return newArray
}
/**
 * Object to param
 * {a: 1, b: 2} => a=1&b=2
 * json[key]暂不做encodeURIComponent处理，路由跳转时如果有中文等特殊字符，会自动转换一次；避免被转2次的问题。
 * */
export function object2param(json) {
  if (!json) return ''
  return cleanArray(
    Object.keys(json).map((key) => {
      if (!json[key]) return ''
      return key + '=' + encodeURI(json[key])
    })
  ).join('&')
}
/**
 * 将对象添加当作参数拼接到URL上面
 * @param baseUrl 需要拼接的url
 * @param obj 参数对象
 * @returns {string} 拼接后的对象
 * 例子:
 *  let obj = {a: '3', b: '4'}
 *  setObjToUrlParams('www.baidu.com', obj)
 *  ==>www.baidu.com?a=3&b=4
 */
export function setObjToUrlParams(baseUrl: string, obj: Record<string, string>): string {
  let parameters = ''
  let url = ''
  for (const key in obj) {
    parameters += key + '=' + encodeURIComponent(obj[key]) + '&'
  }
  parameters = parameters.replace(/&$/, '')
  if (/\?$/.test(baseUrl)) {
    url = baseUrl + parameters
  } else {
    url = baseUrl.replace(/\/?$/, '?') + parameters
  }
  return url
}

/**
 * render 图标
 * */
export function renderIcon(name: string, size?: string, color?: string) {
  return () =>
    h(XIcon, {
      name,
      size,
      color
    })
}

/**
 *  查询树型灵气对应的节点
 * */
let treeResult: any = null
export function getTreeItem(data: any[], key?: string | number): any {
  for (const item of data) {
    if (item.key === key) {
      treeResult = item
      break
    } else {
      if (item.children && item.children.length) {
        if (treeResult && treeResult.key === key) {
          break
        } else {
          getTreeItem(item.children, key)
        }
      }
    }
  }
  return treeResult
}

/**
 * 遍历selected仅为true的id串
 * */
export function filterCheckedIds(data: any[], ids: number[] = []) {
  data?.forEach((item) => {
    if (item.children && item.children.length > 0) {
      filterCheckedIds(item.children, ids)
    } else if (item.selected) {
      ids.push(item.id)
    }
  })
  return ids
}

/**
 * 格式日期时间
 * */
export function formatDate(time: any, b = 'yyyy-MM-dd') {
  if (!arguments.length || !time) {
    return ''
  }
  let date
  if (typeof time === 'object') {
    date = time
  } else {
    if (typeof time === 'string') {
      if (/^\d+$/.test(time)) {
        time = parseInt(time)
      } else {
        time = time.replace(/\-/gi, '/')
      }
    }
    if (typeof time === 'number' && time.toString().length === 10) {
      time = time * 1000
    }
    date = new Date(time)
  }
  const c: Record<string, unknown> = {
    'M+': date.getMonth() + 1,
    'd+': date.getDate(),
    'h+': date.getHours(),
    'm+': date.getMinutes(),
    's+': date.getSeconds(),
    'q+': Math.floor((date.getMonth() + 3) / 3)
  }
  if (/(y+)/.test(b)) {
    b = b.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
  }
  for (const a in c) {
    if (new RegExp('(' + a + ')').test(b)) {
      b = b.replace(RegExp.$1, RegExp.$1.length === 1 ? String(c[a]) : ('00' + c[a]).substr(('' + c[a]).length))
    }
  }
  return b
}

/**
 * 按字符串获取对象内的对应的值
 * getObjectValue({}, 'a.b[0].c')
 * **/
export function getObjectValue(object: any, prop: string) {
  const arr = prop.replace(/]/g, '').replace(/\[/g, '.').split('.')
  const len = arr.length
  let current = object
  for (let i = 0; i < len; i++) {
    // 防止空数据处理
    if (current[arr[i]] === undefined) {
      return undefined
    }
    current = current[arr[i]]
  }
  return current
}

/**
 * 当前时间日期选择器特有的选项
 * **/
export function formatPickerOptions(type: number) {
  const now = new Date()
  const start = new Date()
  switch (type) {
    case 2:
      start.setDate(start.getDate() - 1)
      return [start, start]
    case 3:
      start.setDate(start.getDate() - 7)
      return [start, now]
    case 4:
      start.setDate(start.getDate() - 30)
      return [start, now]
    case 5:
      start.setDate(start.getDate() - 60)
      return [start, now]
    case 6:
      start.setDate(start.getDate() - 90)
      return [start, now]
    case 7:
      start.setDate(start.getDate() - 3)
      return [start, now]
    default:
      return [now, now]
  }
}

/**
 * 小数点后补多位0   ==>  12.00000000 || 12.12340000
 * */
export function formatZero(number = 0, n = 2) {
  if (n <= 0) {
    return Math.round(number)
  }
  number = Math.round(number * Math.pow(10, n)) / Math.pow(10, n) // 四舍五入
  return Number(number).toFixed(n) // 补足位数
}

// 数据格式化保留小数点   ==>  12,345.12 || 12345.12
export function formatNumber(value = 0, precision = 2, type = false) {
  const multiple = Math.pow(10, precision)
  if (type) {
    return (Math.round(value * multiple) / multiple).toLocaleString()
  } else {
    return Math.round(value * multiple) / multiple
  }
}
/**
 * 添加cdn图片优化参数 ?x-oss-process=image/quality,q_75/format,webp
 * @param {string} url 图片地址
 * @param {number} w 尺寸
 * @param {number} q 质量
 * */
export function formatCdn(url: string, w = 300, q = 85, format?: string) {
  const pixelRatio = window.devicePixelRatio || 2
  const oss = ['?x-oss-process=image']

  if (!/\?/gi.test(url)) {
    // 宽度处理
    if (pixelRatio === 2) {
      oss.push(`resize,w_${w}`)
      oss.push(`quality,q_${q}`)
    } else if (pixelRatio <= 1) {
      oss.push(`resize,w_${formatNumber(w / 2, 0)}`)
      oss.push(`quality,q_${formatNumber(q * 1.1, 0)}`)
    } else if (pixelRatio > 2) {
      oss.push(`resize,w_${formatNumber(w * 1.5, 0)}`)
      oss.push('quality,q_75')
    } else {
      oss.push('quality,q_75')
    }

    // 图片格式
    if (/.gif$/gi.test(url)) {
      oss.push('format,gif')
    } else {
      if (format) {
        oss.push(format)
      } else {
        oss.push('format,webp')
      }
    }
    return [url, oss.join('/')].join('')
  } else {
    return url
  }
}

/**
 * 删除JSON对象中的空值对象
 * JSON.stringify(obj, replacer)
 * */
export function replacer(key: any, value: any) {
  if (value === null || value === '') {
    return undefined // never return null or empty strings in our JSON
  }
  if (Array.isArray(value)) {
    return value.filter((v) => ![undefined, null, ''].includes(v))
  }
  return value
}

/**
 * css对象格式为行间css
 * **/
export function formatStyle(object: any) {
  const style: Record<string, any> = {}
  for (const key in object) {
    const value =
      ['marginBottom', 'marginLeft', 'marginRight', 'fontSize', 'padding', 'margin', 'borderRadius'].includes(key) &&
      /^(\-|\+)?\d+$/.test(<string>object[key])
        ? `${object[key]}px`
        : object[key]
    switch (key) {
      case 'marginBottom':
        style['margin-bottom'] = value
        break
      case 'marginLeft':
        style['margin-left'] = value
        break
      case 'marginRight':
        style['margin-right'] = value
        break
      case 'fontSize':
        style['font-size'] = value
        break
      case 'backgroundColor':
        style['background-color'] = value
        break
      case 'backgroundImage':
        style['background-image'] = `url(${value})`
        break
      case 'textAlign':
        style['text-align'] = value
        break
      case 'color':
        style['color'] = value
        break
      case 'fontWeight':
        style['font-weight'] = value
        break
      case 'padding':
        style['padding'] = value
        break
      case 'margin':
        style['margin'] = value
        break
      case 'borderRadius':
        style['border-radius'] = value
        break
      case 'overflow':
        style['overflow'] = value
        break
    }
  }
  return style
}

// 计算中英文字数
export function formatWordCount(value: string | number) {
  let count = 0
  if (value) {
    const content = String(value || '')
    for (let a = content.length, n = -1, r = 0; r < a; r++) {
      n = content.charCodeAt(r)
      count += n >= 0 && n <= 128 ? 0.5 : 1
    }
  }
  return Math.ceil(count)
}

// 打开新页面
export function openWindow({ name, query = {} }: { name: string; query?: Record<string, any> }) {
  const route = router.resolve({ name: name })
  const url = setObjToUrlParams(route.href, query)
  window.open(url)
}

// 关闭当前窗口
export function closeWindow() {
  window.opener = null
  window.open('', '_self')
  window.close()
}

// 获取图片属性
export function getImageInfo(url: string) {
  return new Promise((resolve, reject) => {
    if (url) {
      const el = new Image()
      el.src = url
      el.onload = function () {
        resolve({
          width: el.width,
          height: el.height
        })
        el.remove()
      }
    } else {
      reject()
    }
  })
}

/**
 * 格式化大数值及单位  1234567 => 1百万
 * **/
export function formatCount(value: number | string) {
  const count = Number(value)
  if (count >= 100000000) {
    return formatNumber(count / 100000000, 1) + '亿'
  } else if (count >= 10000000) {
    return formatNumber(count / 10000000, 1) + '千万'
  } else if (count >= 10000) {
    return formatNumber(count / 10000, 1) + '万'
  } else {
    return count
  }
}

/**
 * @param {string} params
 * @returns {Object}
 */
export function param2Object(params: string) {
  if (!params || params.length === 0) {
    return {}
  }
  const paramString = decodeURIComponent(params)
  let paramList = []
  const paramObj = <any>{}
  if (paramString.indexOf('&') >= 0) {
    paramList = paramString.split('&')
  } else {
    paramList[0] = paramString
  }
  paramList.forEach((value) => {
    paramObj[value.split('=')[0]] = decodeURIComponent(value.split('=')[1])
  })
  return paramObj
}

/**
 * 格式成一个英文逗号分隔字符，去重
 * @value{string}
 * **/
export function formatBatchValue(value: string) {
  if (value) {
    const arr = String(value)
      .replace(/^\s{1,}/, '')
      .replace(/\s{1,}$/g, '')
      .replace(/\s{1,}/g, ',')
      .replace(/ |	/gi, '')
      .replace(/，|\n/gi, ',')
      .replace(/、{1,}/gi, ',')
      .replace(/^,{1,}|,{1,}$/g, '')
      .replace(/,{2,}/g, ',')
      .split(',')
    return Array.from(new Set(String(arr).split(','))).join(',')
  } else {
    return ''
  }
}
export function updateByPath(origin: any, path: string, value: any) {
  const arr = path.replace(/]/g, '').replace(/\[/g, '.').split('.')
  let current = origin
  for (let i = 0, len = arr.length; i < len; i++) {
    if (i === len - 1) {
      current[arr[i]] = value
    } else {
      current = current[arr[i]]
    }
  }
}
export function bytesToSize(bytes: any) {
  if (!bytes) return '0 KB'
  const k = 1024
  const sizes = ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseInt(String(bytes / Math.pow(k, i))) + sizes[i]
}
/**
 * 辗转相除法 求最大公约数
 * **/
export const divisorValueFunction = function (m = 960, n = 540) {
  let u = +m
  let v = +n
  let t = v
  while (v !== 0) {
    t = u % v
    u = v
    v = t
  }
  return u
}

export function parseTime(time: string | number | Date, b = 'yyyy-MM-dd hh:mm:ss') {
  if (!arguments.length) {
    return ''
  }
  let date
  if (typeof time === 'object') {
    date = time
  } else {
    if (typeof time === 'string') {
      if (/^\d+$/.test(time)) {
        time = parseInt(time)
      } else {
        time = time.replace(/\-/gi, '/')
      }
    }
    if (typeof time === 'number' && time.toString().length === 10) {
      time = time * 1000
    }
    date = new Date(time)
  }
  const c = {
    'M+': date.getMonth() + 1,
    'd+': date.getDate(),
    'h+': date.getHours(),
    'm+': date.getMinutes(),
    's+': date.getSeconds(),
    'q+': Math.floor((date.getMonth() + 3) / 3),
    S: date.getMilliseconds()
  }
  if (/(y+)/.test(b)) {
    b = b.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
  }
  for (const a in c) {
    if (new RegExp('(' + a + ')').test(b)) {
      b = b.replace(RegExp.$1, RegExp.$1.length === 1 ? c[a] : ('00' + c[a]).substr(('' + c[a]).length))
    }
  }
  return b
}
/**
 * 格式化字条长度，英文算0.5
 * **/
export function formatLength(value = '') {
  if (!value) return 0
  const content = String(value)
  const len = 0
  let t = 0
  for (let a = content.length, n = -1, r = 0; r < a; r++) {
    n = content.charCodeAt(r)
    t += n >= 0 && n <= 128 ? 0.5 : 1
  }
  return len + Math.ceil(t)
}

/**
 * https://www.npmjs.com/package/jsencrypt
 * 通过公钥进行加密后的数据
 * **/
export function encryptJSEncrypt(val: string | number) {
  try {
    const encrypt = new JSEncrypt()
    encrypt.setPublicKey(String(VITE_JSENCRYPT_RSA))
    return encrypt.encrypt(String(val))
  } catch (e) {
    console.warn('通过公钥进行加密后的数据错误->', e)
    return null
  }
}
/**
 * 银行卡号脱敏处理
 * **/
export function maskBankCardNumber(value: string) {
  // 使用正则表达式匹配银行卡号中间的数字部分
  const regex = /(\d{4})\d+(\d{4})/
  const cardNumber = value || ''
  // 替换匹配的部分为脱敏的内容
  return cardNumber.replace(regex, (_, firstPart, lastPart) => {
    const maskedPart = '*'.repeat(cardNumber.length - firstPart.length - lastPart.length)
    return `${firstPart}${maskedPart}${lastPart}`
  })
}
